package for_all;

// -----------------------------------------------------------------------------
// Importanweisungen
import chat_server.ManageRooms;
import chat_server.ManageUser;
import chat_server.UserClientHandler;
import java.awt.Frame;
import java.io.Serializable;
import java.util.ArrayList;


public class User implements Serializable {
       
    // -------------------------------------------------------------------------
    // Variablendeklarationen
    private String userName;
    private int userPassword;
    private boolean online;
    private UserStati userStatus;
    private String room;
    private UserClientHandler clientHandler;
    private ArrayList<PrivateChat> privateChats;
    
    public User.LogInAnswer loginAnswer;
    
    
    // -------------------------------------------------------------------------
    // Konstruktor
    // --> neuer Benutzer
    public User (String userName, String userPassword) {
        
        this.userName       = userName;
        this.userPassword   = userPassword.hashCode();
        this.online         = false;
        this.room           = "--null--";
        this.userStatus     = User.UserStati.normal;
        this.privateChats   = new ArrayList();
    }
    
    
    // -------------------------------------------------------------------------
    // Konstruktor #2
    // --> import
    public User (String userName, int userPassword, User.UserStati status) {
        
        this.userName       = userName;
        this.userPassword   = userPassword;
        this.online         = false;
        this.room           = "--null--";
        this.userStatus     = status;
        this.privateChats   = new ArrayList();
    }
    
    
    // <editor-fold defaultstate="collapsed" desc="Benutzername"> 
    // -------------------------------------------------------------------------
    // Funktionen zum Benutzernamen
    // -------------------------------------------------------------------------
    
    // Benutzername auslesen
    public String getUserName() {
        
        if (this.userName == null) {
            return "";
        } else {
            return this.userName;
        }
        
    }
    
    // Benutzername auslesen --> JList
    @Override
    public String toString() {
        if ("--null--".equals(this.getRoomName())) {
          return this.getUserName();
        } else {
            return this.getUserName() + " [" + this.getRoomName() + "]";
        }
        
    }
    // </editor-fold>
    
    
    // <editor-fold defaultstate="collapsed" desc="Passwort"> 
    // -------------------------------------------------------------------------
    // Funktionen zum Passwort
    // -------------------------------------------------------------------------
    
    // Kontrolle des übergebenen Passwortes (String als Parameter)
    public boolean checkPassword(String password) {
        
        if (this.userPassword == password.hashCode()) {
            return true;
        } else {
            return false;
        }
        
    }
    
    
    // Kontrolle des übergebenen Passwortes (User als Parameter)
    public boolean checkPassword(User usr) {
        
        if (usr.userPassword == this.userPassword) {
            return true;
        } else {
            return false;
        }
        
    }
    
    
    // Passwort holen
    public String getPassword() {
        return String.valueOf(this.userPassword);    
    }
    
    // </editor-fold>
    
    
    // <editor-fold defaultstate="collapsed" desc="Status"> 
    // -------------------------------------------------------------------------
    // Funktionen zum Benutzerstatus
    // -------------------------------------------------------------------------
    
    // Stati
    public enum UserStati {
        verwarnt, getrennt, geblockt, normal
    }
    
    
    // Benutzerstatus holen
    public UserStati getUserStatus() {
        return this.userStatus;
    }
    
    
    // online/offline?
    public boolean getOnline() {
        return this.online;
    }
    
    
    // setzen des Benutzerstatus
    public boolean setUserStatus (UserStati newStatus, boolean notNotification) {
        
        switch (newStatus) {
            
            case normal:
                if (this.getOnline() && !notNotification) {
                    this.clientHandler.sendMessageToClient(new Message("Deine Verwarnung wurde aufgehoben!", "Admin", "Server", false)); 
                }
                this.userStatus = newStatus;
                return true;
                
            case verwarnt:
                if (this.getOnline()) {
                    this.clientHandler.sendMessageToClient(new Message("Du wurdest verwarnt!", "Admin", "Server", false));
                    this.userStatus = newStatus;
                    return true;
                } else {
                    return false;
                }
                
            case getrennt:
                if (this.getOnline()) {
                    this.clientHandler.sendMessageToClient(new Message("Du wirst nun aus Gründen vom Server getrennt!", "Admin", "Server", false));
                    this.clientHandler.sendLogOutToUser(LogOutUser.LogoutReason.Kicked, false);
                    this.userStatus = newStatus;
                    return true;
                } else {
                    return false;
                }
                
            case geblockt:
                if (this.getOnline()) {
                    this.clientHandler.sendMessageToClient(new Message("Du wirst nun aus Gründen von nun an von diesem Server geblockt!", "Admin", "Server", false)); 
                    this.clientHandler.sendLogOutToUser(LogOutUser.LogoutReason.Banned, true);
                }
                this.userStatus = newStatus;
                return true;
                
            default:
                this.userStatus = newStatus;
            
        }
        
        return false;
        
    }
    
    
    // setzen online/offline
    public void setOnline (boolean online) {
        this.online = online;
    }
    
    //</editor-fold>
    
    
    // <editor-fold defaultstate="collapsed" desc="Raum"> 
    // -------------------------------------------------------------------------
    // Funktionen zum Raum, in dem der User ist
    // -------------------------------------------------------------------------
    
    // Raum für User setzten
    public void setRoom(String roomName) {
        if ("".equals(roomName) || roomName == null) {
            this.room = "--null--";
        } else {
            this.room = roomName;
        }
    }
    
    
    // Name von Raum in dem der User ist, holen
    public String getRoomName() {
        return this.room;
    }
    //</editor-fold>
    
    
    // <editor-fold defaultstate="collapsed" desc="LogIn-Answer">
    // -------------------------------------------------------------------------
    // LogIn-Answer: Antwort des Servers an Client mit Antowrt auf LogIn
    // -------------------------------------------------------------------------
    
    // Setzten einer LogIn Antwort für den User (neues Objekt)
    public void setLogInAnswer(LoginResult result, String userName, String[] onlineUser, String[] roomNames) {
        this.loginAnswer = new User.LogInAnswer(result, userName, onlineUser, roomNames);
    }
    
    
    // mögliche Antworten auf LogIn
    public enum LoginResult {
        accepted, wrongPassword, nonRegistrated, alreadyOnline, banned
    }
    

    // Klasse für die Antwort auf Login von Server an Client für User
    public class LogInAnswer implements Serializable {
        
        // Variablendeklarationen
        private LoginResult result;
        private String  userName;
        private PopUp fail;
        public String[] onlineUserList;
        public String[] rooms;            //in Eintrag i steht der Raumname von dem User, der in onlineUserList an Stelle i steht
        
        
        // Konstruktor
        public LogInAnswer(LoginResult result, String userName, String[] onlineUser, String[] roomNames) {
            
            this.result   = result;
            this.userName = userName;
            this.onlineUserList = onlineUser;
            this.rooms = roomNames;
        }
       
        
        // Fehler/Begrüßung ausgeben
        public void ThrowMessage(Frame parentFrame) {
            
            switch(result) {
                case accepted:         this.fail = new PopUp(parentFrame, "Lieber " + this.userName + ", herzlich Willkommen!", "Willkommen");
                                       break;
                case nonRegistrated:   this.fail = new PopUp(parentFrame, this.userName + ", wir haben dich, da wir deinen Namen noch nicht kennen, bei uns registriert!", "Willkommen");
                                       break;
                case wrongPassword:    this.fail = new PopUp(parentFrame, "Du hast ein falsches Passwort für deinen User " + this.userName + " angegeben. Bitte versuchen Sie es erneut!", "Falsches Passwort");
                                       break;
                case alreadyOnline:    this.fail = new PopUp(parentFrame, "Du, " + this.userName + ", bist schon angemeldet. Bitte melde dich erst dort ab!");
                                       break;
                case banned:           this.fail = new PopUp(parentFrame, "Du, " + this.userName + ", bist auf diesem Server gesperrt!", "Gesperrt",PopUp.MessageTyp.Warning);
                                       break;
                default:               this.fail = new PopUp(parentFrame, "Leider konnten wir dich, " + this.userName + ", nicht anmelden.", PopUp.MessageTyp.Error);
            }
            
        }
        
    
        public LoginResult getStatus() {
            return this.result;
        }
        
    }
    //</editor-fold>
    
    
    // -------------------------------------------------------------------------
    //
    public void removeAllPrivateChats() {
        this.privateChats = null; 
    }
    
    
    // -------------------------------------------------------------------------
    //
    public UserClientHandler getClientHandler() {
        return this.clientHandler;
    }
    
    
    // -------------------------------------------------------------------------
    //
    public void setClientHandler (Transporter trans, ManageUser mangUsr, ManageRooms mangRms) {
        this.clientHandler = new UserClientHandler(this, trans, mangUsr, mangRms);
        this.clientHandler.start();
    }
    
    
    // -------------------------------------------------------------------------
    //
    public void clearClientHandler() {
        this.clientHandler.interrupt();
        this.clientHandler = null;
    }
    
    
    // -------------------------------------------------------------------------
    // neu private Unterhaltung mit User als beteiligten
    public void addPrivateChat(PrivateChat privChat) {
        
        this.privateChats.add(privChat);
        
        // Wenn Einladung nicht von diesem User kommt
        // --> User über private Chat benachrichtigen
        if (privChat.getUser1() == null ? this.getUserName() != null : !privChat.getUser1().equals(this.getUserName())) {
            
            this.clientHandler.informUserAboutPrivateChat(privChat);
            
        }
        
        
    }
    
    
    // -------------------------------------------------------------------------
    // privaten Chat entfernen
    public void removePrivateChat(PrivateChat.RemovePrivateChat remPrCh) {
        
        for (int i = 0; i < this.privateChats.size(); i++) {
            
            // richtigen PrivateChat finden
            if (remPrCh.otherUser == null ? this.privateChats.get(i).getUser1() == null : remPrCh.otherUser.equals(this.privateChats.get(i).getUser1())) {
                
                if (remPrCh.otherUser == null ? this.getUserName() == null : remPrCh.otherUser.equals(this.getUserName())) {
                    this.clientHandler.informUserAboutDeletedPrivateChat(this.privateChats.get(i).getDeleteMessage(this.privateChats.get(i).getUser2()));
                    this.privateChats.remove(i);
                } else {
                    this.privateChats.remove(i);
                }
                
            } else if (remPrCh.otherUser == null ? this.privateChats.get(i).getUser2() == null : remPrCh.otherUser.equals(this.privateChats.get(i).getUser2())) {
                if (remPrCh.otherUser == null ? this.getUserName() == null : remPrCh.otherUser.equals(this.getUserName())) {
                    this.clientHandler.informUserAboutDeletedPrivateChat(this.privateChats.get(i).getDeleteMessage(this.privateChats.get(i).getUser1()));
                    this.privateChats.remove(i);
                } else {
                    this.privateChats.remove(i);
                }
            }
        }
    }
    
    
    // LogOut-Klasse
    static public class LogOutUser implements Serializable {
        public enum LogoutReason {
            ServerClosed, Banned, Kicked, ClientClosed;
        }
        
        private LogoutReason reason;
        
        public LogOutUser(LogoutReason reason) {
            this.reason = reason;
        }
        public LogoutReason getReason() {
            return reason;
        }
    }
    
    //Wird an den Client gesendet, wenn sich ein neuer client anmeldet
    static public class NewUserLoggedOn implements Serializable {
        private String userName;
        private String roomName;
        
        public NewUserLoggedOn(String userName, String roomName) {
            this.userName = userName;
            this.roomName = roomName;
        }
        
        public String getUserName() {
            return userName;
        }
        
        public String getRoomName() {
            return roomName;
        }
    }
    
    
    // -------------------------------------------------------------------------
    // Wird an den Client gesendet, wenn sich ein Client abmeldet
    static public class UserLoggedOff implements Serializable {
        private String userName;
        private String roomName;
        
        public UserLoggedOff(String userName, String roomName) {
            this.userName = userName;
            this.roomName = roomName;
        }
        
        public String getUserName() {
            return userName;
        }
        
        public String getRoomName() {
            return roomName;
        }
    }
}